package com.gitee.feizns.dynamic.reflect;

import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;

/**
 * <b>关于lambda表达式的反射工具类</b>
 *
 * @author feizns
 * @since 2019/8/4 0004
 */
public abstract class LambdaUtils {

    private static final String WRITE_REPLACE_METHOD = "writeReplace";

    /**
     * <b>获取lambda表达式所引用的方法引用方法名称</b>
     * <pre>{@code
        static class User { public static String getName(String a) {return "HELLO WORLD";}}
        public static void main(String[] args) {
            //直接使用lambda的方式获取不到.
            Getter<String, String> getter1 = a -> a;
            System.out.println(getImplMethodName(getter1)); //lambda$main$cd5f30ce$1
            //一定要使用方法引用才获取到引用的方法名称
            Getter<String, String> getter2 = User::getName;
            System.out.println(getImplMethodName(getter2)); //getName
        }
     * }</pre>
     * @param lambda 方法引用
     * @return 返回所引用的方法名称
     */
    public static String getImplMethodName(Serializable lambda) {
        return getSerializedLambda(lambda).getImplMethodName();
    }

    /***
     * <b>获取类对应的Lambda</b>
     * @see SerializedLambda
     * @param fn lambda表达式函数
     * @return lambda表达式信息
     */
    public static SerializedLambda getSerializedLambda(Serializable fn){
        try {
            Method method = fn.getClass().getDeclaredMethod(WRITE_REPLACE_METHOD);
            method.setAccessible(Boolean.TRUE);
            return (SerializedLambda) method.invoke(fn);
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException(e);
        }
    }

}
